namespace CRM_Perf_BenchMark
{
	using System;
	using System.Collections.Generic;
	using Microsoft.VisualStudio.TestTools.WebTesting;
	using System.Net;
	using System.Text;
	using System.Xml;
	using System.Web.Services.Protocols;

	using Microsoft.Crm.Sdk.Proxy;
    

	/// <summary>
	/// 1. Start at homepage
	/// 2. Click on New ServiceActivity button on top
	/// 3. Click on Schedule and fill data(all this is done with CrmService call for the test)
	/// 4. Select a service from the lookup dialog
    /// 5. Click "Find Available Times" button
    /// 6. Select a proposal from the grid and click "Schedule"
    /// 7. Complete the Service Activity form
    /// 8. Click Save and Close
	/// </summary>

	public class ProposalBook : CrmWebTest
	{
		public void ProposalBook_PreWebTest(object sender, PreWebTestEventArgs e)
		{
			Guid orgId = EntityManager.Instance.GetRandomOrg();

            EntityRequest er = new EntityRequest();
            er.Type = EntityNames.Users;
            er.ReturnAs = EntityNames.Users;
            er.ParentID = orgId;

            System.Collections.Hashtable userProps = new System.Collections.Hashtable();
            if (e.WebTest.Context.ContainsKey("UserRole"))
            {
                userProps.Add("role", e.WebTest.Context["UserRole"]);
                er.Props = userProps;
            }
            
            System.Collections.Hashtable Entities = EntityManager.Instance.GetEntities(er);

            user = (CRMEntity)Entities[EntityNames.Users];

			tokenKey = EntityManager.Instance.ReadTokenKey(user["organizationid"]);

			e.WebTest.UserName = user["domainName"];
			e.WebTest.Password = user["userpassword"];
			
			service = EntityManager.Instance.GetNextORGEntity(EntityNames.Service, orgId);
			EntityManager.Instance.FreeEntity(service);
			
			crmServer = user["CrmServer"];

			_crmService = new CrmService();
			_crmService.Url = user["CrmServer"] + "/MSCRMServices/2007/CrmService.asmx";
			_crmService.Timeout = 1000000;

			string[] split = user["domainName"].Split(new char[] { '\\' });
			if (split.Length > 1)
			{
				string domain = split[0];
				string username = split[1];
				_crmService.UnsafeAuthenticatedConnectionSharing = true;
				_crmService.ConnectionGroupName = user["domainName"];
				_crmService.Credentials = new NetworkCredential(username, user["userpassword"], domain);
			}
			_crmService.CrmAuthenticationTokenValue = new CrmAuthenticationToken();
			_crmService.CrmAuthenticationTokenValue.OrganizationName = user["organizationname"];

			_crmService.CrmAuthenticationTokenValue.AuthenticationType = AuthenticationType.AD;
			
			content = GetProposal(new Guid(service["serviceid"]));
		}

		public void ProposalBook_PostWebTest(object sender, PostWebTestEventArgs e)
		{
			EntityManager.Instance.FreeEntity(user);
			_crmService = null;
		}
        
		public ProposalBook()
		{
			WebRequest.RegisterPrefix("crm", new crmRequestFactory());

			this.Proxy = null;
			PreWebTest += new EventHandler<PreWebTestEventArgs>(ProposalBook_PreWebTest);
			PostWebTest += new EventHandler<PostWebTestEventArgs>(ProposalBook_PostWebTest);
		}

		public override IEnumerator<WebTestRequest> GetRequestEnumerator()
		{
			int typeCode = 4214;
			gridXml = GridXmlHelper.ServicePage(service[EntityIDNames.Service]);

			this.BeginTransaction("ProposalSearch");
			
            activities_serviceappointment_edit_aspx actsae = new activities_serviceappointment_edit_aspx(user);
			yield return (actsae);

            referer = actsae.lastResponse.ResponseUri.AbsoluteUri;

			_forms_FormScript_js_aspx f = new _forms_FormScript_js_aspx(user);
			f.etc = 4214;
			f.FormType = "main";
			f.FormName = "crmForm";
            headerItem = new WebTestRequestHeader("referer", referer);
            f.Headers.Add(headerItem);
			yield return (f);

			_controls_notes_notesdata_aspx note = new _controls_notes_notesdata_aspx(user);
			note.ParentEntity = 4214;
			note.EnableInlineEdit = true;
			note.EnableInsert = true;
			yield return (note);

    		DateTimeService.DateTimeWebService dtws = new DateTimeService.DateTimeWebService();
			CrmRequest wtr = null;
			try
			{
				dtws.GetFormattedDate(DateTime.Today.ToString());
			}
			catch (crmException x)
			{
				wtr = (CrmRequest)x.wtr;
				wtr.Url = Utils.ReplaceServerName(wtr.Url, user);
			}
			yield return (wtr);
			yield return (wtr);

			sm_activityscheduling_schedulingdialog_aspx smactsch = new sm_activityscheduling_schedulingdialog_aspx(user);
			smactsch.ActivityTypeCode = 4214;
			yield return (smactsch);

			_controls_lookup_lookupsingle_aspx lookupsingle = new _controls_lookup_lookupsingle_aspx(user);
			lookupsingle.Class = "ServicesEnabled";
			lookupsingle.objecttypes = "4001";
			lookupsingle.browse = 0;
            lookupsingle.ShowNewButton = 1;
            lookupsingle.ShowPropButton = 1;
            lookupsingle.DefaultType = 0;
			yield return (lookupsingle);

            _controls_lookup_lookupdialogs_css_aspx lookupdialog = new _controls_lookup_lookupdialogs_css_aspx(user);
            lookupdialog.lcid = 1033;
            yield return (lookupdialog);

			ServiceWebService.ServiceWebService serviceweb = new ServiceWebService.ServiceWebService();
			wtr = null;

			try 
            { 
                serviceweb.Retrieve(new Guid(service["serviceid"]), new string[] { "duration" }); 
            }
			catch (crmException x)
			{
				wtr = (CrmRequest)x.wtr;
				wtr.Url = Utils.ReplaceServerName(wtr.Url, user);

				string urlPath = wtr.Url.Remove(0, crmServer.Length);
				urlPath = urlPath.Remove(0, user["organizationName"].Length + 1);

				rpcInfo = Utils.GenerateWRPCToken(urlPath, user, tokenKey);

				headerItem = new WebTestRequestHeader();
				headerItem.Name = "crmwrpctokentimestamp";
				headerItem.Value = rpcInfo.timeStamp.ToString();
				wtr.Headers.Add(headerItem);
				headerItem = new WebTestRequestHeader();
				headerItem.Name = "crmwrpctoken";
				headerItem.Value = rpcInfo.token;
				wtr.Headers.Add(headerItem);
				wtr.Method = "Post";
			}
			yield return (wtr);

			AppGridWebService.AppGridWebService agws = new AppGridWebService.AppGridWebService();
			WebTestRequest wtrRefresh = null;
			try 
            { 
                agws.Refresh(gridXml); 
            }
			catch (crmException x)
			{
				wtrRefresh = x.wtr;
				wtrRefresh.Url = Utils.ReplaceServerName(wtrRefresh.Url, user);

				string urlPath = wtrRefresh.Url.Remove(0, crmServer.Length);
				urlPath = urlPath.Remove(0, user["organizationName"].Length + 1);

				rpcInfo = Utils.GenerateWRPCToken(urlPath, user, tokenKey);

				headerItem = new WebTestRequestHeader();
				headerItem.Name = "crmwrpctokentimestamp";
				headerItem.Value = rpcInfo.timeStamp.ToString();
				wtrRefresh.Headers.Add(headerItem);
				headerItem = new WebTestRequestHeader();
				headerItem.Name = "crmwrpctoken";
				headerItem.Value = rpcInfo.token;
				wtrRefresh.Headers.Add(headerItem);
				wtrRefresh.Method = "Post";
			}
			yield return (wtrRefresh);

			this.EndTransaction("ProposalSearch");
            
			this.BeginTransaction("ProposalBook");

            dtws = new DateTimeService.DateTimeWebService();
            wtr = null;
            try
            {
                dtws.GetFormattedDate(DateTime.Today.ToString());
            }
            catch (crmException x)
            {
                wtr = (CrmRequest)x.wtr;
                wtr.Url = Utils.ReplaceServerName(wtr.Url, user);
            }

            yield return (wtr);
            
            yield return (wtr);

            serviceweb = new ServiceWebService.ServiceWebService();
            wtr = null;

            try
            {
                serviceweb.Retrieve(new Guid(service["serviceid"]), new string[] { "duration" });
            }
            catch (crmException x)
            {
                wtr = (CrmRequest)x.wtr;
                wtr.Url = Utils.ReplaceServerName(wtr.Url, user);

                string urlPath = wtr.Url.Remove(0, crmServer.Length);
                urlPath = urlPath.Remove(0, user["organizationName"].Length + 1);

                rpcInfo = Utils.GenerateWRPCToken(urlPath, user, tokenKey);

                headerItem = new WebTestRequestHeader();
                headerItem.Name = "crmwrpctokentimestamp";
                headerItem.Value = rpcInfo.timeStamp.ToString();
                wtr.Headers.Add(headerItem);
                headerItem = new WebTestRequestHeader();
                headerItem.Name = "crmwrpctoken";
                headerItem.Value = rpcInfo.token;
                wtr.Headers.Add(headerItem);
                wtr.Method = "Post";
            }
            yield return (wtr);

            dtws = new DateTimeService.DateTimeWebService();
            wtr = null;
            try
            {
                dtws.GetFormattedDate(DateTime.Today.ToString());
            }
            catch (crmException x)
            {
                wtr = (CrmRequest)x.wtr;
                wtr.Url = Utils.ReplaceServerName(wtr.Url, user);
            }

            yield return (wtr);

            _controls_number_formatNumber_xsl formatNumber = new _controls_number_formatNumber_xsl(crmServer);

            yield return (formatNumber);

			ActivitiesWebService.ActivitiesWebService abc = new ActivitiesWebService.ActivitiesWebService();

			WebTestRequest book = null;

			try
			{
				abc.Book(content, typeCode);
			}
			catch (crmException x)
			{
				book = x.wtr;
				
                book.Url = Utils.ReplaceServerName(book.Url, user);

				string urlPath = book.Url.Remove(0, crmServer.Length);
				urlPath = urlPath.Remove(0, user["organizationName"].Length + 1);

				rpcInfo = Utils.GenerateWRPCToken(urlPath, user, tokenKey);

				headerItem = new WebTestRequestHeader();
				headerItem.Name = "crmwrpctokentimestamp";
				headerItem.Value = rpcInfo.timeStamp.ToString();
				book.Headers.Add(headerItem);
				headerItem = new WebTestRequestHeader();
				headerItem.Name = "crmwrpctoken";
				headerItem.Value = rpcInfo.token;
				book.Headers.Add(headerItem);
				book.Method = "Post";
			}
			yield return (book);

			this.EndTransaction("ProposalBook");
		}

		private CRMEntity user;
		private CRMEntity service;
		private static string gridXml;
		private string crmServer;
		private CrmService _crmService;
		XmlNode content;
		private string tokenKey;

		private WRPCInfo rpcInfo;
		private WebTestRequestHeader headerItem;
        private string referer;

		private XmlNode GetProposal(Guid serviceId)
		{
			AppointmentRequest appointmentRequest = new AppointmentRequest();

			appointmentRequest.ServiceId = serviceId;
			appointmentRequest.Direction = SearchDirection.Forward;
			appointmentRequest.NumberOfResults = 1;
			appointmentRequest.SearchWindowStart = CrmDateTime.FromUser(DateTime.Now.AddDays(1));
			appointmentRequest.SearchWindowEnd = CrmDateTime.FromUser(DateTime.Today.AddYears(1));

			SearchRequest request = new SearchRequest();

			request.AppointmentRequest = appointmentRequest;

			SearchResponse response;
			try
			{
				response = _crmService.Execute(request) as SearchResponse;
			}
			catch (SoapException e)
			{
				System.Diagnostics.Trace.WriteLine(e.ToString());
				return null;
			}
			catch (Exception e)
			{
				System.Diagnostics.Trace.WriteLine(e.ToString());
				return null;
			}
			SearchResults results = response.SearchResults;

			if (results.Proposals.Length < 1)
			{
				throw new InvalidProgramException("no proposals were returned");
			}

			StringBuilder body = new StringBuilder();
			body.Append(@"<serviceappointment>");
			body.Append(@"<subject>PerfTest</subject>");
			body.Append(@"<statuscode>4</statuscode>");
			body.Append(@"<serviceid type=""4001"">{" + serviceId.ToString() + "}</serviceid>");
			body.Append(@"<resources>");

			foreach (ProposalParty party in results.Proposals[0].ProposalParties)
			{
				body.Append(@"<activityparty>");
				body.Append(@"<partyid name=""" + party.DisplayName + @""" type=""4000"">&#x7B;" + party.ResourceId + @"&#x7D;</partyid>");
				body.Append(@"<resourcespecid>&#x7B;" + party.ResourceSpecId.ToString() + @"&#x7D;</resourcespecid>");
				body.Append(@"<effort>" + party.EffortRequired + @"</effort>");
				body.Append(@"</activityparty>");
			}

			body.Append(@"</resources>");
			body.Append(@"<scheduledstart>" + FormatDateTime(results.Proposals[0].Start.UserTime, ":") + @"</scheduledstart>");
			body.Append(@"<scheduleddurationminutes>60</scheduleddurationminutes>");
			body.Append(@"<scheduledend>" + FormatDateTime(results.Proposals[0].End.UserTime, ":") + @"</scheduledend>");
			body.Append(@"<isalldayevent>0</isalldayevent>");
			body.Append(@"<ownerid type=""8"">{" + user[EntityIDNames.User] + "}</ownerid>");
			body.Append(@"<prioritycode>1</prioritycode>");
			body.Append(@"</serviceappointment>");

			XmlDocument doc = new XmlDocument();
			doc.LoadXml(body.ToString());

			return doc;
		}

		private string FormatDateTime(DateTime date, string seperator)
		{
			string year = date.Year.ToString();
			string month = (date.Month < 10) ? "0" + date.Month.ToString() : date.Month.ToString();
			string day = (date.Day < 10) ? "0" + date.Day.ToString() : date.Day.ToString();
			string hour = (date.Hour < 10) ? "0" + date.Hour.ToString() : date.Hour.ToString();
			string minute = (date.Minute < 10) ? "0" + date.Minute.ToString() : date.Minute.ToString();
			string second = (date.Second < 10) ? "0" + date.Second.ToString() : date.Second.ToString();

			return (
				year + "-" +
				month + "-" +
				day + "T" +
				hour + seperator +
				minute + seperator +
				second);

		}       
	}
}